package commands;

import observers.FileEventPublisher;
import utils.EditorContext;
import workspaces.WorkSpace;
import workspaces.WorkSpaceCenter;

public class CommandParser {
    // 默认填充一个workspace, 兼容历史逻辑
    private WorkSpace workSpace = new WorkSpace("defaultWorkspace");

    private boolean ensureEditing() {
        if (workSpace.getContext().getState() != EditorContext.EditorState.EDITING) {
            System.out.println("You must load a file first.");
            return false;
        }
        return true;
    }

    public Command parse(String rawText) {
        Command commandResult = null;
        String[] parts = rawText.split(" ", 2);
        String command = parts[0].toLowerCase();

        switch (command) {
            case "load":
                if (parts.length < 2) {
                    System.out.println("Usage: load <file_path>");
                    break;
                }

                if (!parts[1].endsWith(".md")) {
                    System.out.println("Only .md files can be loaded.");
                    break;
                }
                String fileName = parts[1];
                // 获取每个文件对应WorkSpace
                WorkSpaceCenter workSpaceCenter = WorkSpaceCenter.getInstance();
                workSpace = workSpaceCenter.getWorkSpace(fileName);
                if (workSpace != null) {
                    System.out.println("Switched to an existed workspace: " + fileName);
                } else {
                    workSpace = new WorkSpace(fileName);
                    workSpaceCenter.registerWorkSpace(fileName, workSpace);
                    System.out.println("Switched to a new workspace: " + fileName);
                }
                commandResult = new LoadCommand(workSpace.getContext(), fileName);
                break;
            case "save":
                if (!ensureEditing()) {
                    break;
                }
                if (parts.length > 1) {
                    System.out.println("Only save command needed, no more file or anything else");
                    break;
                }
                if (workSpace.getContext().getCurrentFilePath() != null) {
                    commandResult = new SaveCommand(workSpace.getContext(), workSpace.getContext().getCurrentFilePath());
                    break;
                } else {
                    throw new IllegalArgumentException("No file path provided and no file currently loaded.");
                }
            case "insert":
                if (!ensureEditing()) {
                    break;
                }
                if (parts.length < 2) {
                    System.out.println("Usage: insert [line] text");
                    break;
                }
                // 检查是否提供了行号
                String[] insertParts = parts[1].split(" ", 2);
                if (insertParts.length == 1) {
                    // 如果只有一个部分, 则假定整个内容是要插入的文本
                    commandResult = new InsertCommand(workSpace.getContext(), insertParts[0]);
                    break;
                } else {
                    try {
                        int lineNumber = Integer.parseInt(insertParts[0]);
                        commandResult = new InsertCommand(workSpace.getContext(), lineNumber, insertParts[1]);
                        break;
                    } catch (NumberFormatException e) {
                        // 如果第一部分不是数字，则假定整个内容是要插入的文本
                        commandResult = new InsertCommand(workSpace.getContext(), parts[1]);
                        break;
                    }
                }
            case "delete":
                if (!ensureEditing()) {
                    break;
                }
                // 检查是否提供了行号
                String[] deleteParts = parts[1].split(" ", 2);
                if (deleteParts.length == 1) {
                    try {
                        int lineNumber = Integer.parseInt(parts[1]);
                        commandResult = new DeleteCommand(workSpace.getContext(), lineNumber, parts[1]);
                        break;
                    } catch (NumberFormatException e) {
                        commandResult = new DeleteCommand(workSpace.getContext(), parts[1]);
                        break;
                    }
                }
                else if (deleteParts.length == 2 && deleteParts[0].equals("~")){
                    commandResult = new DeleteCommand(workSpace.getContext(), deleteParts[1]);
                    break;
                }
                else {
                    System.out.println("Usage: delete <text> or delete <lineNumber> or delete ~ <text>");
                    break;
                }
            case "append-head":
                if (!ensureEditing()) {
                    break;
                }
                if (parts.length < 2) {
                    System.out.println("Usage: append-head <text>");
                    break;
                }
                commandResult = new InsertCommand(workSpace.getContext(), 1, parts[1]);
                break;
            case "append-tail":
                if (!ensureEditing()) {
                    break;
                }
                if (parts.length < 2) {
                    System.out.println("Usage: append-tail <text>");
                    break;
                }
                commandResult = new InsertCommand(workSpace.getContext(), parts[1]);
                break;
            case "undo":
                if (!ensureEditing()) {
                    break;
                }
                if (parts.length > 1) {
                    System.out.println("Only undo command needed, no more file or anything else");
                    break;
                }
                commandResult = new UndoCommand(workSpace.getContext());
                break;
            case "redo":
                if (!ensureEditing()) {
                    break;
                }
                if (parts.length > 1) {
                    System.out.println("Only redo command needed, no more file or anything else");
                    break;
                }
                commandResult = new RedoCommand(workSpace.getContext());
                break;
            case "list":
                if (!ensureEditing()) {
                    break;
                }
                if (parts.length > 1) {
                    System.out.println("Only list command needed, no more file or anything else");
                    break;
                }
                commandResult = new ListCommand(workSpace.getContext());
                break;
            case "list-tree":
                if (!ensureEditing()) {
                    break;
                }
                if (parts.length > 1) {
                    System.out.println("Only list_tree command needed, no more file or anything else");
                    break;
                }
                commandResult = new ListTreeCommand(workSpace.getContext());
                break;
            case "dir-tree":
                if (!ensureEditing()) {
                    break;
                }
                else if (parts.length < 2) {
                    commandResult = new ListTreeCommand(workSpace.getContext());
                    break;
                }
                else{
                    commandResult = new DirTreeCommand(workSpace.getContext(), parts[1]);
                    break;
                }
            case "history":
                if (parts.length == 2) {
                    if (!parts[1].matches("[0-9]+") || Integer.parseInt(parts[1]) <= 0) {
                        System.out.println("Usage: history [<positive number>]");
                    } else {
                        commandResult = new HistoryCommand(workSpace.getContext(), Integer.parseInt(parts[1]));
                    }
                    break;
                } else if (parts.length == 1) {
                    commandResult = new HistoryCommand(workSpace.getContext(), -1);
                    break;
                } else {
                    System.out.println("Usage: history [<positive number>]");
                    break;
                }
            case "stats":
                if (parts.length == 2  && (parts[1].equals("current") || parts[1].equals("all"))) {
                    if (parts[1].equals("current")) {
                        if (!ensureEditing()) {
                            break;
                        }
                    }
                    commandResult = new StatsCommand(workSpace.getContext(), parts[1]);
                    break;
                }else if(parts.length == 1){
                    commandResult = new StatsCommand(workSpace.getContext(), "all");
                    break;
                }
                else {
                    System.out.println("Usage: status [current or all]");
                    break;
                }
            case "exit":
                if (parts.length >= 2) {
                    System.out.println("Usage: only need to input exit.");
                }else{
                    commandResult = new ExitCommand(workSpace.getContext());
                }
                break;
            case "spaces":
                if (parts.length >= 2) {
                    System.out.println("Usage: only need to input spaces.");
                } else {
                    commandResult = new SpacesCommand(workSpace.getContext());
                }
                break;
            default:
                System.out.println("Unknown command. Available commands: load, save, insert, append-head, append-tail, delete, undo, redo, list, list-tree, dir-tree, history, stats [all | current], spaces, exit");
                break;
        }
        if (commandResult != null){
            FileEventPublisher.getInstance().notifyObservers(rawText);
        }
        return commandResult;
    }

}